# src/data_analysis/comment_analyzer.py

import requests
import json
import re
import os
import logging
from functools import lru_cache
from models.comment_schema import TagDict
from models.database import DatabaseManager
from models.comment_schema import AnalyzedComment
from utils.config_loader import Config


logger = logging.getLogger(__name__)

'''
完整 AI 分析逻辑
'''

@lru_cache(maxsize=1)
def get_label_rules(session=None):
    """
    获取标签规则，支持传入 session 参数
    :param session: sqlalchemy.orm.Session 实例（可选）
    :return: 标签规则字典
    """
    if session is None:
        config = Config()
        db_manager = DatabaseManager(config.DB_CONFIG)
        session = db_manager.Session()

    try:
        tags = session.query(TagDict).order_by(TagDict.id).all()

        rules = {}

        # 添加一级标签
        for tag in tags:
            if tag.level == 1:
                rules[tag.name] = []

        # 添加二级标签
        for tag in tags:
            if tag.level == 2 and tag.parent_id is not None:
                parent = next((t for t in tags if t.id == tag.parent_id), None)
                if parent and parent.name in rules:
                    rules[parent.name].append(tag.name)

        return rules
    finally:
        if session is not None and session.is_active:
            session.close()


PROMPT_TEMPLATE = """
请对以下 YouTube 用户评论进行结构化分析：

<原始评论>
{comment_text}
</原始评论>

### 要求：
1. 输出原始文本
2. 提供中文翻译（保留技术术语）
3. 分类到最精确的二级标签（可以多选）
4. 不添加额外内容，确保格式严格为 JSON 格式

### 输出格式示例：
{{
  "original_text": "...",
  "translated_text": "...",
  "primary_label": "...",
  "secondary_labels": [...],
  "confidence_score": 0.95  # 可选：置信度评分
}}

### 标签体系：
{label_rules_json}
"""


def clean_json_string(json_str):
    """
    清理 DeepSeek 返回的 JSON 字符串
    - 去除首尾空白
    - 移除控制字符
    - 去掉 Markdown 代码块标记
    - 修复不合法的键名
    """
    if not json_str:
        return ""

    # 去除首尾空白和控制字符
    cleaned = re.sub(r'[\x00-\x1F\x7F]', '', json_str.strip())

    # 去掉 ```json 包裹
    cleaned = re.sub(r'^```json\s*', '', cleaned).rstrip('`')

    # 替换非法键名中的换行和空格
    cleaned = re.sub(r'(\s*"\s*)(?:\\")?([^\s"]+)(?=\s*:)', r'\1\2', cleaned)

    return cleaned


class CommentAnalyzer:
    def __init__(self, api_key=None):
        self.api_key = api_key or os.getenv("DEEPSEEK_API_KEY")
        self.endpoint = "https://api.deepseek.com/v1/chat/completions"
        self.headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }

    def analyze_single(self, raw_data):
        """
        对单条评论进行分析
        :param raw_data: 原始评论数据（字典或 RawComment 实例）
        :return: 分析结果字典 或 None
        """
        # 提取 comment_text
        if isinstance(raw_data, dict):
            comment_text = raw_data.get("comment_text", "")
        else:
            comment_text = getattr(raw_data, "comment_text", "")

        if not comment_text or not isinstance(comment_text, str):
            return None

        # 提取 like_count（如果存在）
        like_count = raw_data.get("like_count", 0) if isinstance(raw_data, dict) else getattr(raw_data, "like_count", 0)

        system_prompt = """你是一个专业的市场分析助手。请严格按照以下规则处理用户评论：
            1. 对每条评论进行中文翻译
            2. 根据提供的标签体系进行分类
            3. 支持多标签匹配
            4. 输出格式为JSON对象"""

        label_rules = get_label_rules()

        user_prompt = PROMPT_TEMPLATE.format(
            comment_text=comment_text,
            label_rules_json=json.dumps(label_rules, ensure_ascii=False)
        )

        payload = {
            "model": "deepseek-chat",
            "messages": [
                {"role": "system", "content": system_prompt},
                {"role": "user", "content": user_prompt}
            ],
            "temperature": 0.1,
            "response_format": {"type": "json_object"}
        }

        try:
            logger.debug(f"📡 发送请求到: {self.endpoint}")
            logger.debug(f"📡 请求头: {self.headers}")
            logger.debug(f"📡 请求体: {json.dumps(payload, ensure_ascii=False)[:800]}...")

            response = requests.post(self.endpoint, headers=self.headers, json=payload)

            result = response.json()
            content = result.get("choices", [{}])[0].get("message", {}).get("content", "")

            logger.debug(f"🧠 DeepSeek 原始返回: {content[:500]}...")
            cleaned_content = clean_json_string(content)

            try:
                parsed_result = json.loads(cleaned_content) if cleaned_content else {}
            except json.JSONDecodeError as e:
                logger.error(f"❌ JSON 解析失败: {str(e)}")
                parsed_result = {}

            if not parsed_result:
                logger.warning("⚠️ DeepSeek 返回空结果，使用默认值替代")
                return {
                    "id": raw_data.get("id") if isinstance(raw_data, dict) else getattr(raw_data, "id", None),
                    "video_source_id": raw_data.get("video_source_id") if isinstance(raw_data, dict) else getattr(raw_data, "video_source_id", None),
                    "original_text": comment_text[:500],
                    "translated_text": "解析失败",
                    "primary_label": "其他反馈",
                    "secondary_labels": ["无效信息"],
                    "confidence_score": 0.4,
                    "like_count": like_count
                }

        except Exception as e:
            logger.error(f"分析失败: {str(e)}")
            return {
                "id": raw_data.get("id") if isinstance(raw_data, dict) else getattr(raw_data, "id", None),
                "video_source_id": raw_data.get("video_source_id") if isinstance(raw_data, dict) else getattr(raw_data, "video_source_id", None),
                "original_text": comment_text[:500],
                "translated_text": "解析失败",
                "primary_label": "其他反馈",
                "secondary_labels": ["无效信息"],
                "confidence_score": 0.4,
                "like_count": like_count
            }

        return {
            "id": raw_data.get("id") if isinstance(raw_data, dict) else getattr(raw_data, "id", None),
            "video_source_id": raw_data.get("video_source_id") if isinstance(raw_data, dict) else getattr(raw_data, "video_source_id", None),
            "original_text": parsed_result.get("text", comment_text),
            "translated_text": parsed_result.get("translated_text", "解析失败"),
            "primary_label": parsed_result.get("primary_label", "其他反馈"),
            "secondary_labels": parsed_result.get("secondary_labels", ["无效信息"]),
            "confidence_score": parsed_result.get("confidence_score", 0.4),
            "like_count": like_count
        }
    

    def translate(self, text):
        """
        使用 LLM 翻译文本
        :param text: 原文
        :return: 中文翻译
        """
        prompt = f"""
        请将以下英文内容翻译成中文：
        
        {text}
        
        要求：
        - 保持时间轴格式不变
        - 仅返回翻译后的内容，不要添加额外说明
        """
        return self._call_llm(prompt)


    def batch_analyze(self, comments_data):
        """
        批量分析评论数据（支持 RawComment 对象或字典列表）
        """
        if not comments_data:
            logger.warning("⚠️ 输入数据为空，跳过分析")
            return []

        # 统一转换为字典列表
        comments_list = []
        for comment in comments_data:
            if hasattr(comment, 'to_dict'):
                comments_list.append(comment.to_dict())  # 假设 RawComment 有 to_dict 方法
            elif isinstance(comment, dict):
                comments_list.append(comment)
            else:
                # 如果是字符串或其他类型，包装成标准格式
                comments_list.append({
                    "comment_text": str(comment),
                    "like_count": getattr(comment, "like_count", 0)
                })

        results = []

        for comment in comments_list:
            try:
                raw_result = self.analyze_single(comment)
            except Exception as e:
                logger.error(f"❌ 分析单条评论失败: {str(e)}")
                continue

            if not raw_result:
                text = comment.get("comment_text", "")[:100] or "未知内容"
                logger.debug(f"🔍 分析结果为空，跳过该条评论: {text}...")
                continue

            results.append(raw_result)

        return [AnalyzedComment(**item) for item in results]